home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
AUDIOPLAYERS
/
AMP
/
!Amp
/
Docs
/
AMPlayer
next >
Wrap
Text File
|
1999-09-26
|
14KB
|
390 lines
AMPlayer
--------
This is a module for playing Audio MPEG files through the computer sound
output. It will select the 8 or 16 bit output depending on the normal
configuration (and availability).
AMPlayer module
===============
This is the program that does the actual work. There are various reasons for
wanting to control the module directly instead of through the frontend:
1. You get better control, and can automate things using obey files, etc.
2. You may want to write your own frontend.
3. The fancy frontend uses memory and CPU time that might be better used
elsewhere.
For these purposes, the module has several *commands and SWIs.
* Commands
==========
*AMPlay starts playing an Audio MPEG file. When -Q[ueue] is present, the file
will be played after the current one finishes, otherwise immediately.
When -C[ue] is present, the file will be started, but with the player in pause
mode.
Syntax: *AMPlay [-Queue|-Cue] <filename>
*AMStop stops the MPEG file playing
Syntax: *AMStop
*AMInfo prints information about the player module status, and about the file
playing, if any.
Syntax: *AMInfo
*AMVolume sets the playback volume. Range is 0 to 127, with 113 as initial
value.
Syntax: *AMVolume <number>
*AMLocate locates the specified point in the file currently playing/paused.
Syntax: *AMLocate <hours>[:<minutes>[:<seconds>]]
System variables
================
AMPlayer$Buffer$*
-----------------
You can set up the audio buffer size to use by setting one or more of these
variables. When the buffer is created, the size is determined by the best
match of the filename and one of these variables. The more characters that
match, the better, and the variable with the most will control the buffer
size.
The idea is that the best buffer size somewhat depends on the file access
speed. The faster the device, the smaller buffer you can get away with, and
the better response you will get from things like fast forward/rewind.
CDFS for example is very slow. Therefore, I have the following variables:
AMPlayer$Buffer$ 20
AMPlayer$Buffer$SCSI 16
AMPlayer$Buffer$CDFS 40
The effect of this is, that CDFS in general will get size 40. SCSI is fast
and gets 16, and everything else (ADFS, RAMFS etc.) get 20.
It is possible (but not necessary in my case) to include part of the disc
name too (e.g. "AMPlayer$Buffer$ADFS::Winnie"), to make the buffer size
depend on the drive as well as the FS. Indeed, you can go further and
include some directory path as well, though that will probably be rarely
used (with softlinks perhaps?).
The size is given in "blocks". These are currently about 4.5K. The reason
for not giving it in Kbytes is, that it is highly likely that the buffer
requirement will change (decrease) in later versions, while still having
the same resulting buffer time. Giving it in blocks means you don't have
to change the value when the block size changes.
AMPlayer$FileBuffer
-------------------
If this variable is set, it is used to decide the size of the input buffer.
On slow filing systems, the sound may mute while fetching more data. Raising
the input buffer size will help. The size is given in kbytes. If the variable
doesn't exist, the default size is 32K.
AMPlayer$Volume
---------------
Setting this to some value between 0 and 127, will determine the default
volume when the module is later loaded. It only has effect before loading;
to change the volume afterwards, use *AMVolume.
If unset, volume 113 is used at startup.
SWI calls
=========
SWI AMPlayer_Play
-----------------
On entry R0 = Flags
bit0 Queue only
bit1 Cue
R1 ->Filename
On exit All registers preserved
Bit0,1 of R0 determines the action:
0 Starts playing the file immediately, after stopping any other file
currently playing.
1 Registers the filename as "next" file (see File info block below).
The file will start when the current one finishes normally (i.e. not
if it is stopped by an explicit call to AMPlayer_Stop or *AMStop).
If there is no file currently playing, the behaviour is exactly as
with bit0 of R0 clear.
2 Starts the file immediately, but frozen at frame 0 in pause mode.
Use SWI AMPlayer_Pause to start playback (which will start with a
very much shorter delay than if just using Play).
3 Currently undefined.
Note: There can only be one "next" file at any moment. The name registered
can safely be changed to something else, just by calling this SWI again.
It is possible to cancel the registered file by calling this SWI with
bit0 of R0 set, and R1 pointing to a null string.
Note: Given sufficient playback buffer and medium access speed, the current
file will continue seamlessly into the next one. This is good for live
music, that has been divided into separate files.
SWI AMPlayer_Stop
-----------------
On entry R0 = Flags
bit0 Cut to next file
On exit All registers preserved
Stops playback. If bit0 of R0 is set, playback continues with a queued file
if any.
SWI AMPlayer_Pause
------------------
On entry R0 = Flags
bit0 Continue
On exit All registers preserved
Action is determined by bit0 of R0:
0 Halts playback immediately.
1 Continues playback immediately.
Pause mode may also be cancelled by stopping. If Stop is used to cut to the
next file, or if a different file is started, pause mode will continue to
be in effect, freezing the new file at time=0. This can be used to ensure
that playback starts at the instant of calling AMPlayer_Pause (as opposed to
calling AMPlayer_Play, which can have a delay while opening the file etc.)
SWI AMPlayer_Locate
-------------------
On entry R0 = Flags
R1 = Target time
On exit All registers preserved
Locates the position of the target time, and continues playback (or pausing)
from there.
This has no effect unless the status is either Playing, Locating or Paused.
This may take some time, and the playback buffer may empty (which will mute
the sound).
The time given here corresponds to the elapsed time returned from
AMPlayer_Info below. This is true even when the elapsed time is wrong (see
below). So when, at time X, the Info call returns the wrong time Y, giving
time Y to this call will still start playing at the right time X.
Playback can only start on a frame boundary, so the resolution of the start
point is around 2 cs (for 128kbit/sec, 44.1kHz frames).
SWI AMPlayer_Info
-----------------
On entry R0 = Flags
On exit R0 = Player status
Other registers depend on status, as follows:
Status Info
R0=0 Dormant None
R0=1 Starting R1 ->Filename
R0=2 Locating R1 ->Filename
R2 ->File info block (see below)
R3 ->Frame info block (see below)
R4 = Target time
R0=3 Playing R1 ->Filename
R2 ->File info block
R3 ->Frame info block
R0=4 Paused R1 ->Filename
R2 ->File info block
R3 ->Frame info block
R0=5 Stopping R1 ->Filename
R0=6 Changing R1 ->New filename
R0=7 Cueing R1 ->Filename
Note: When locating, the current time can be read from the file info block,
as it moves toward the target time returned in R4.
Note: The registers not mentioned above are preserved. This provides an easy
way of determining the info returned, without decoding R0. In Basic:
SYS "AMPlayer_Info",,"" TO ,Filename$,FIB%
This will set Filename$ to either "" or the filename. Similarily, FIB%
will be 0 if there is no info at this stage, or a pointer to it if there
is.
Note: There is a brief period when the status might be returned as 2 or 3, but
where there is no valid frame info block, because the first frame hasn't
been read. In that case, R3 will be preserved, so the code mentioned
above will still work.
SWI AMPlayer_Control
--------------------
On entry R0 = Reason code
Other registers depend on code:
R0=0 Read/write main volume
R1 = New volume (0-127), or -1 to read
On exit:
R1 = Old volume
R0=1 Read/write size of audio buffer
R1 = New size in bytes, or -1 to read
On exit:
R1 = Old size
If the buffer isn't currently created, this controls
how large it will be when it eventually is.
If it exists, OS_ChangeDynamicArea is used to change
the size. This may fail with an error, even if some
of the job was done (this can happen when reducing the
size, as the amount that can be released depends on
what is currently being played).
If it succeeds, the sound will be broken up at least
once. So it is best to set the size while not playing.
R0=2 Set stack check level
R1 = New level (in words), or 0 for default
When receiving a callback, the SVC stack depth is
checked to see if the kernel is reasonably unthreaded.
By using this call, you can control what is considered
"reasonable". The default value is currently 64, i.e.
if there are more than 64 words on the stack by the
time of the callback, a new callback will be registered
later instead. Setting this too low will cause the
player to stall, and you can only stop it by killing
the module.
Returned structures
===================
File info block
---------------
Offset Meaning
0 Flags:
bit0 set: Total time valid
bit1 set: Elapsed time valid
bit2 set: ID3 tag info pointers valid
bit3 set: VU values valid
bit4 set: Error message pointer valid
bit5 set: Next filename pointer valid
bit6-31 reserved
4 Buffer usage ratio in %
8 Projected total time in cs if bit0 of flags set (see below)
12 Time elapsed in cs if bit1 of flags set
16 Pointer to ID3 song title if bit2 of flags set (see below)
20 Pointer to ID3 artist if bit2 of flags set
24 Pointer to ID3 album name if bit2 of flags set
28 Pointer to ID3 year string if bit2 of flags set
32 Pointer to ID3 comment if bit2 of flags set
36 Left channel VU if bit3 set (see below)
40 Right channel VU if bit3 set
44 Main volume (0..127)
48 Pointer to most recent error/warning message if bit4 of flags set
52 Pointer to filename of the "next" file if bit 5 of R0 is set
56 ID3 genre (a number) if bit2 of flags set
Note: All the string-pointers are addresses of 0-terminated strings, which are
to be read only. If you want to keep on referring to the same string,
copy it into your own workspace. The ones pointed to can and will change
according to the 'state of play'. This is not true for all of them, so
don't rely on that either (i.e. call the SWI when you want to update
your view of the current status). Also, it's important to check the
appropriate flag bit before referring to any pointers. Not doing so can
result in a program that seems to work, but fails in mysterious ways
once in a while.
Note: The projected total time is correct if the current frame type (bitrate,
etc.) stays constant until the end of the file. It will be wrong if
either
1. the file size is unknown, e.g. if playing a stream, or
2. the frame type will later change in a way that alters the number of
bytes per frame.
None of the above exceptions are true in the vast majority of mpeg files.
The first case is determined by the module, and bit0 of the flags will
be clear. The second case cannot be known in advance, and it will also
affect the elapsed time. No matter what happens, the time will always
move forward, it just might not be counting centiseconds in these cases.
Note: Any of the ID3 tag strings may be null, indeed, the often are. This
indicates that the tag field consists entirely of spaces.
Note: When the VU level is available, it is a number between 0 and 255. The
value is from -42 to 0 dB, in 1/6th dB steps. The level is the peak of
the average level since last calling this SWI.
Frame info block
----------------
Offset Meaning
0 MPEG version as 3 ASCII chars and a 0 terminator, e.g. "2.0"
4 Layer type (1..3). 0 is unknown layer
8 Sampling frequency in Hz
12 Bitrate in kbit/sec
16 Mode
0: Stereo
1: Joint-stereo
2: Dual channel
3: Single channel
20 Number of channels
24 Flags
bit0: Copyright
bit1: Original
bit2: CRC
28 Pointer to left channel DCT array
32 Pointer to right channel DCT array
Credits
=======
I have no documentation about the Audio MPEG format. So this module was
produced by porting several other free mpeg decoders, extracting the
necessary bits, then optimising it for RISC OS/ARM. The latter by rewriting
the algorithms in most cases. Therefore, there are concepts and code bits
by many different people left in this module. I will try to list the most
obvious "contributors", as I could certainly not have done it without access
to their work:
Michael Hipp & Oliver Fromme wrote mpg123, which was ported and used.
Tomislav Uzelac wrote "amp", similarily ported and learned from.
ISO MPEG Audio Subgroup Software Simulation Group, dist10 package was used
as the main source of information about the intended functionality, rather
than the actual implementation of it.
And thanks must go to the testers that put up with the early bugs
(in order of appearance)...
Gerph, Kira, unCiscy, JanM, Zhadnost, Cocodude, MoZes, Lennier, Xargle,
Ben, TwoFlower, Forrey, & Nick.
License
=======
I don't speak Legalese, so if any lawyers have trouble understanding the
following, please ask a grownup for help.
In its current form, this is free for copying and use by anyone, subject to
the following:
If you want to include any of this as part of a commercial product, you need
my permission.
It can be freely supplied with PD, Freeware, and similar programs, as long as
proper credit is given, and no money is charged for them in any way.
At some point, I will include the source, and this licence will probably be
replaced with the GPL, but that will not affect the status of previous
versions.
Contact
=======
Questions, etc. should be addressed to:
Thomas Olsson
tolsson@isa.dknet.dk